﻿using ATEC.ATDataCoreNET;
using ATEC.GeometryNET;
using SSDPNET;
using System;
using System.Windows.Forms;
using SZEWNet.SZEWCoreNet;
using SZEWBridgeNet.SZEWBridgeRebar;
using System.Collections.Generic;
using ATEC.ATDataCoreNET.ATObjects;
using SSDPNET.DataCore;
using System.Runtime.CompilerServices;
namespace SZEWBridgeUtilExample
{
    public partial class BridgeRebarTestForm : Form
    {
        public BridgeRebarTestForm()
        {
            InitializeComponent();
        }

        private static ATSceneRef sceneref = ScenesFunctions.SceneRefGetActive();//获得当前激活的场景
        private static double uor = ScenesFunctions.SceneRefGetUorPerMeter(sceneref);
        private static double uorMM = uor / 1000;
        private static double rebarDiameter = 20 * uorMM;//钢筋外径

        //计算自定义弯钩(自定义弯钩：根据设计弯钩长度，计算平直段长度)
        private static AnchorOption CalculateCustomizedAnchor(bool bOutputMessage = false)
        {
            string outputMessage = "自定义弯钩：根据设计弯钩长度，计算平直段长度\n";

            //设置弯钩参数
            AnchorOption anchorOption = new AnchorOption();
            anchorOption.SetAnchorAngle(XAngle.PI.Radians / 4.0 * 3);
            anchorOption.SetPosition(AnchorPosition.POS_ANCHOR_START);
            anchorOption.SetRebarDiameter(rebarDiameter);
            anchorOption.SetNominalDiameter(rebarDiameter);
            anchorOption.SetBendingDiameter(rebarDiameter);

            //按规范初始化平直段长度
            SZEWBridgeRebarUtil.InitFlatLength(out anchorOption);
            outputMessage += string.Format("按规范计算的平直段长度：{0}\n", anchorOption.GetFlatLength());

            //获取默认设计弯钩长度
            double designLength = anchorOption.GetTotalLength();
            outputMessage += string.Format("默认设计弯钩长度：{0}\n", designLength);

            //自定义弯钩支持更改设计弯钩长度，反算平直段长度
            designLength += 20 * uorMM;
            SZEWBridgeRebarUtil.CalculateFlatLength(out anchorOption, designLength);

            outputMessage += string.Format("更改后的设计弯钩长度：{0}\n", designLength);
            outputMessage += string.Format("反算平直段长度：{0}\n", anchorOption.GetFlatLength());

            if (bOutputMessage)
                System.Windows.Forms.MessageBox.Show(outputMessage);

            return anchorOption;
        }

        //计算非自定义弯钩(非自定义弯钩：根据平直段长度，计算设计弯钩长度)
        private static AnchorOption CalculateNoncustomizedAnchor(bool bOutputMessage = false)
        {
            string outputMessage = "非自定义弯钩：根据平直段长度，计算设计弯钩长度\n";

            //设置弯钩参数
            AnchorOption anchorOption = new AnchorOption();
            anchorOption.SetAnchorAngle(XAngle.PI.Radians / 4.0 * 3);
            anchorOption.SetPosition(AnchorPosition.POS_ANCHOR_END);
            anchorOption.SetRebarDiameter(rebarDiameter);
            anchorOption.SetNominalDiameter(rebarDiameter);
            anchorOption.SetBendingDiameter(rebarDiameter);

            //按规范初始化平直段长度
            SZEWBridgeRebarUtil.InitFlatLength(out anchorOption);
            double flatLength = anchorOption.GetFlatLength();
            outputMessage += string.Format("按规范计算的平直段长度：{0}\n", flatLength);

            //获取默认设计弯钩长度
            double designLength = anchorOption.GetTotalLength();
            outputMessage += string.Format("默认设计弯钩长度：{0}\n", designLength);

            //非自定义弯钩支持更改平直段长度，重新计算设计弯钩长度
            flatLength += 20 * uorMM;
            outputMessage += string.Format("更改后的平直段长度：{0}\n", flatLength);
            anchorOption.SetFlatLength(flatLength);

            //获取修改平直段长度后的设计弯钩长度
            designLength = anchorOption.GetTotalLength();
            outputMessage += string.Format("更改后的设计弯钩长度：{0}\n", designLength);

            if (bOutputMessage)
                System.Windows.Forms.MessageBox.Show(outputMessage);

            return anchorOption;
        }


        private void button_customizedAnchor_Click(object sender, EventArgs e)
        {
            CalculateCustomizedAnchor(true);
        }

        private void button_noncustomizedAnchor_Click(object sender, EventArgs e)
        {
            CalculateNoncustomizedAnchor(true);
        }

        private static BaseGroupInfo GetBaseGroupInfo()
        {
            BaseGroupInfo baseGroupInfo = new BaseGroupInfo(rebarDiameter, "测试钢筋");
            AnchorOption startAnchorOption = CalculateCustomizedAnchor(false);//起始弯钩
            AnchorOption endAnchorOption = CalculateNoncustomizedAnchor(false);//终止弯钩
            baseGroupInfo.SetStartAnchorOption(startAnchorOption);
            baseGroupInfo.SetEndAnchorOption(endAnchorOption);
            return baseGroupInfo;
        }

        private void button_getOpenCrvAnchor_Click(object sender, EventArgs e)
        {
            //创建不带弯钩的钢筋曲线
            List<XPoint3d> rebarPts = new List<XPoint3d> { XPoint3d.Zero, XPoint3d.Zero + XPoint3d.UnitX * uor };
            CurveSet rebarCrv = CurveSet.CreateLinear(rebarPts, CurveSet.BoundaryType.Open, false);

            //设置钢筋组基本信息
            BaseGroupInfo baseGroupInfo = GetBaseGroupInfo();

            //生成带弯钩的钢筋曲线
            XPoint3d centerPt = XPoint3d.FromXYZ(0, 100, 0);//弯钩弯向Y轴正方向
            XVector3d normal = XVector3d.UnitZ;//弯钩所在平面法向
            CurveSet anchorRebarCrv = SZEWBridgeRebarUtil.GetOpenRebarAnchor(rebarCrv, centerPt, normal, baseGroupInfo);
            if (anchorRebarCrv == null)
                return;

            //加入场景
            ATObject curveSetObj = GeometryToATObject.ToObject(sceneref.GetATScene(), anchorRebarCrv, null);
            if (curveSetObj == null)
                return;

            curveSetObj.AddToScene();
        }

        private void button_getClosedCrvAnchor_Click(object sender, EventArgs e)
        {
            //创建不带弯钩的钢筋曲线
            XPoint3d pt1 = XPoint3d.Zero;
            XPoint3d pt2 = pt1 + XPoint3d.UnitX * uor;
            XPoint3d pt3 = pt2 + XPoint3d.UnitY * uor;
            XPoint3d pt4 = pt1 + XPoint3d.UnitY * uor;


            List<XPoint3d> rebarPts = new List<XPoint3d> { pt1, pt2, pt3, pt4 };
            CurveSet rebarCrv = CurveSet.CreateLinear(rebarPts, CurveSet.BoundaryType.Outer, false);

            //设置钢筋组基本信息
            BaseGroupInfo baseGroupInfo = GetBaseGroupInfo();

            //生成带弯钩的钢筋曲线
            CurveSet anchorRebarCrv = SZEWBridgeRebarUtil.GetCloseRebarAnchor(rebarCrv, baseGroupInfo);
            if (anchorRebarCrv == null)
                return;

            //加入场景
            ATObject curveSetObj = GeometryToATObject.ToObject(sceneref.GetATScene(), anchorRebarCrv, null);
            if (curveSetObj == null)
                return;

            curveSetObj.AddToScene();
        }

        private static void PrintCurve(CurveSet crv, ATScene destScene, UInt32 colorIndex = 0)
        {
            if (crv == null)
                return;

            ATObject curveSetObj = GeometryToATObject.ToObject(destScene, crv, null);
            ObjectPropertiesSetter setter = new ObjectPropertiesSetter();
            setter.SetColor(colorIndex);
            setter.Apply(curveSetObj);
            curveSetObj.AddToScene();
        }

        private static void PrintEllipse3d(XPoint3d center, double radius, ATScene destScene, UInt32 colorIndex = 0)
        {
            XEllipse3d ellipse3d = XEllipse3d.FromCenterRadiusXY(center, radius);
            BasicCurve arc = BasicCurve.CreateArc(ellipse3d);
            CurveSet crv = CurveSet.Create(CurveSet.BoundaryType.Outer);
            crv.Add(arc);
            PrintCurve(crv, destScene, colorIndex);
        }

        private static void PrintText(string text, XPoint3d origin, double height, ATScene destScene)
        {
            //创建文本块属性
            TextBlockProperties tbProp = new TextBlockProperties(destScene);
            tbProp.IsViewIndependent = false;

            //创建文本段落属性
            ParagraphProperties paraProp = new ParagraphProperties(destScene);

            // 创建文字样式
            ATTextStyle textStyle = ATTextStyleExtension.GetActive();
            textStyle.SetProperty(TextStyleProperty.Height, height);
            textStyle.SetProperty(TextStyleProperty.Width, height);

            //创建文本块
            RunProperties runProp = RunPropertiesExtension.Create(textStyle, destScene);
            TextBlock textBlock = new TextBlock(tbProp, paraProp, runProp, destScene); 
            {
                textBlock.AppendText(text);
                textBlock.SetUserOrigin(origin); //定义文本块所在位置
                textBlock.SetOrientation(XMatrix3d.Identity); // 旋转矩阵
            }

            //将text转换为obj 并添加到scene中
            ATObject obj;
            TextHandlerBaseExtension.CreateObject(out obj, textBlock);
            obj.AddToScene();
        }


        private static SzewBPreLongitudinalSteelTendon InitTendonTemplate()
        { 
            //示例：仅构造一个竖弯 + 一个平弯
            SzewBPreHorizontalBending horBending = new SzewBPreHorizontalBending();
            horBending.dYOffsetDistance = 0;
            horBending.sReferSteelTendonName = "VBend";//关联的竖弯名称
            horBending.sHorizontalBendName = "HBend";
            horBending.nIndex = 0;
            horBending.eReferLine = HorizontalReferLine.BOXGIRDER_CENTER_LINE;
            horBending.listXAxial = new List<double> { 0, 28000, 86000, 114000 };
            horBending.listYAxial = new List<double> { 0, 3000, 3000, 0 };
            horBending.listRadius = new List<double> { 0, 0, 0, 0 };

            SzewBPreVerticalBending verBending = new SzewBPreVerticalBending();
            verBending.dYOffsetDistance = 0;
            verBending.sSteelTendonName = "VBend";
            verBending.listXAxial = new List<double> { 0, 25000, 50000, 65000, 90000, 114000 };
            verBending.listZAxial = new List<double> { 0, 5000, 5000, 5000, 5000, 0 };
            verBending.listRadius = new List<double> { 0, 60000, 60000, 60000, 60000, 0 };
            verBending.listZReferFace = new List<VerticalReferFace>
            {   
                VerticalReferFace.TOPBORAD_TOP_FACE, 
                VerticalReferFace.TOPBORAD_TOP_FACE,
                VerticalReferFace.TOPBORAD_TOP_FACE, 
                VerticalReferFace.TOPBORAD_TOP_FACE
            };

            //打印定义的平弯、竖弯点及半径
            //平弯
            {
                List<double> vXAxial = horBending.listXAxial;
                List<double> vYAxial = horBending.listYAxial;
                List<double> vRadius = horBending.listRadius;
                for (int i = 0; i < vXAxial.Count; ++i)
                {
                    XPoint3d pt = XPoint3d.FromXYZ(vXAxial[i], vYAxial[i], 0);
                    PrintEllipse3d(pt, 400, sceneref.GetATScene(), 2);//绿色
                    if (vRadius[i] != 0)
                        PrintText(string.Format("({0},{1},{2})\n R = {3}", pt.X, pt.Y, pt.Z, vRadius[i]), pt, 150, sceneref.GetATScene());
                    else
                        PrintText(string.Format("({0},{1},{2})", pt.X, pt.Y, pt.Z), pt, 150, sceneref.GetATScene());
                }
            }

            //竖弯
            {
                List<double> vXAxial = verBending.listXAxial;
                List<double> vZAxial = verBending.listZAxial;
                List<double> vRadius = verBending.listRadius;
                for (int i = 0; i < vXAxial.Count; ++i)
                {
                    XPoint3d pt = XPoint3d.FromXYZ(vXAxial[i], 0, vZAxial[i]);
                    PrintEllipse3d(pt, 400, sceneref.GetATScene(), 1);//蓝色
                    if (vRadius[i] != 0)
                        PrintText(string.Format("({0},{1},{2})\n R = {3}", pt.X, pt.Y, pt.Z, vRadius[i]), pt, 150, sceneref.GetATScene());
                    else
                        PrintText(string.Format("({0},{1},{2})", pt.X, pt.Y, pt.Z), pt, 150, sceneref.GetATScene());
                }
            }

            //构造钢束模板
            List<SzewBPreHorizontalBending> horBendings = new List<SzewBPreHorizontalBending> { horBending };
            List<SzewBPreVerticalBending> verBendings = new List<SzewBPreVerticalBending> { verBending };
            SzewBPreLongitudinalSteelTendon preLongiTendon = new SzewBPreLongitudinalSteelTendon();
            preLongiTendon.listHorizontalBending = horBendings;
            preLongiTendon.listVerticalBending = verBendings;

            return preLongiTendon;
        }


        private void button_getTendonLinear_Click(object sender, EventArgs e)
        {
            //构造钢束模板
            SzewBPreLongitudinalSteelTendon preLongiTendon = InitTendonTemplate();

            //创建钢束
            SZEWBridgeRebarUtil.CreatePrestressedSteelTendon(preLongiTendon);

            //打印局部线形
            List<TendonGroupLinear> tendonGroupLinears = new List<TendonGroupLinear>();
            SZEWBridgeRebarUtil.GetTendonGroupLinears(out tendonGroupLinears);
            foreach (TendonGroupLinear tendonGroupLinear in tendonGroupLinears)
            {
                if (tendonGroupLinear == null)
                    continue;

                foreach (SingleTendonLinear singleTendonLinear in tendonGroupLinear.listTendonLocalLinears)
                {
                    if (singleTendonLinear == null)
                        continue;

                    PrintCurve(singleTendonLinear.horizontalBendingCrv, sceneref.GetATScene(), 2);//绿色
                    PrintCurve(singleTendonLinear.verticalBendingCrv, sceneref.GetATScene(), 1);//蓝色
                }
            }
        }

        private void button_getTendonSpaceLinear_Click(object sender, EventArgs e)
        {
            //构造钢束模板
            SzewBPreLongitudinalSteelTendon preLongiTendon = InitTendonTemplate();

            //创建钢束
            SZEWBridgeRebarUtil.CreatePrestressedSteelTendon(preLongiTendon);

            //打印线形
            List<TendonGroupLinear> tendonGroupLinears = new List<TendonGroupLinear>();
            SZEWBridgeRebarUtil.GetTendonGroupLinears(out tendonGroupLinears);
            foreach (TendonGroupLinear tendonGroupLinear in tendonGroupLinears)
            {
                if (tendonGroupLinear == null)
                    continue;

                foreach (SingleTendonLinear singleTendonLinear in tendonGroupLinear.listTendonLocalLinears)
                {
                    if (singleTendonLinear == null)
                        continue;

                    //加密后的线形
                    if (singleTendonLinear.spaceCrv != null)
                    { 
                        PrintCurve(singleTendonLinear.spaceCrv, sceneref.GetATScene(), 3);//红色
                        foreach (BasicCurve basicCrv in singleTendonLinear.spaceCrv)
                        {
                            if (basicCrv == null)
                                continue;

                            List<XPoint3d> spaceCrvPts = new List<XPoint3d>();
                            basicCrv.TryGetLineString(spaceCrvPts);
                            foreach (XPoint3d spaceCrvPt in spaceCrvPts)
                            {
                                if (spaceCrvPt == null)
                                    continue;

                                //映射到平弯竖弯面
                                List<XPoint3d> horCrvPts = new List<XPoint3d> { spaceCrvPt,XPoint3d.FromXY(spaceCrvPt.X, spaceCrvPt.Y) };
                                CurveSet horCrv = CurveSet.CreateLinear(horCrvPts, CurveSet.BoundaryType.Open, false);
                                PrintCurve(horCrv, sceneref.GetATScene(), 4);//黄色

                                List<XPoint3d> verCrvPts = new List<XPoint3d> { spaceCrvPt, XPoint3d.FromXYZ(spaceCrvPt.X, 0, spaceCrvPt.Z) };
                                CurveSet verCrv = CurveSet.CreateLinear(verCrvPts, CurveSet.BoundaryType.Open, false);
                                PrintCurve(verCrv, sceneref.GetATScene(), 5);//粉色
                            }


                        }
                    }

                    //采样点
                    if (singleTendonLinear.spaceLocateCrv != null)
                    {
                        foreach (BasicCurve basicCrv in singleTendonLinear.spaceLocateCrv)
                        {
                            if (basicCrv == null)
                                continue;

                            List<XPoint3d> spaceCrvPts = new List<XPoint3d>();
                            basicCrv.TryGetLineString(spaceCrvPts);
                            foreach (XPoint3d spaceCrvPt in spaceCrvPts)
                            {
                                if (spaceCrvPt == null)
                                    continue;

                                PrintEllipse3d(spaceCrvPt, 500, sceneref.GetATScene(), 3);
                                PrintText(string.Format("({0},{1},{2})", spaceCrvPt.X.ToString("0"), spaceCrvPt.Y.ToString("0"), spaceCrvPt.Z.ToString("0")), spaceCrvPt, 85, sceneref.GetATScene());
                            }
                        }
                    }
                }
            }
        }
    }
}
